package cn.zyf;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.apache.pdfbox.pdmodel.PDDocument;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class RmrbDownload {

    private static final String DIR_PATH = "D:\\zyf\\资料\\人民日报";
    private static final String URL = "http://paper.people.com.cn/rmrb/pc/layout/%s%s/%s/node_%s.html";

    public static void main(String[] args) throws Exception {
        new RmrbDownload().run();
    }

    private void run() throws Exception {
        int[] ymd = getYYYYMMDD();
        int year = ymd[0];
        int month = ymd[1];
        int day = ymd[2];

        String sYear = String.valueOf(year);
        String sMonth = month < 10 ? "0" + month : String.valueOf(month);
        String sDay = day < 10 ? "0" + day : String.valueOf(day);

        String dir = sYear + sMonth + sDay;
        log.info("dir: {}", dir);
        String path = DIR_PATH + "\\" + dir;
        File fileDir = new File(path);
        fileDir.mkdirs();

        String url = String.format(URL, sYear, sMonth, sDay, "01");
        String pageContent = getPageContent(url);

        List<String> pages = resolvePages(pageContent);
        for (String page : pages) {
//            sleep(1000);
            pageContent = getPageContent(String.format(URL, sYear, sMonth, sDay, page));
            String[] arr = resolveLink(pageContent);
            String link = arr[0];
            String name = arr[1];
            String downloadUrl = url + "/../" + link;
            downloadPdf(downloadUrl, path + "\\" + name);
        }

    }

    private void sleep(long ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException ignore) {
        }
    }

    private int[] getYYYYMMDD() {
        int[] ymd = new int[3];
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);

//        year = 2025;
//        month = 2;
//        day = 10;

        ymd[0] = year;
        ymd[1] = month;
        ymd[2] = day;
        return ymd;
    }

    private String[] resolveLink(String pageContent) {
        String pattern = "<a href=\"(.*)\\.pdf\" download=\"(.*)\\.pdf\">";
        Pattern compile = Pattern.compile(pattern);
        Matcher matcher = compile.matcher(pageContent);
        if (matcher.find()) {
            return new String[] {matcher.group(1) + ".pdf", matcher.group(2) + ".pdf"};
        }
        throw new RuntimeException("not found");
    }

    private List<String> resolvePages(String pageContent) {
        List<String> list = new ArrayList<>();
        String pattern = "href=\"node_%s.html\"";
        int start = 1;
        while (true) {
            String pageNo = start < 10 ? "0" + start : String.valueOf(start);
            if (!pageContent.contains(String.format(pattern, pageNo))) {
                return list;
            }
            log.info("exist node: {}", pageNo);
            list.add(pageNo);
            start++;
        }
    }

    private void downloadPdf(String pdfUrl, String fileName) throws Exception {
//        pdfUrl = URLDecoder.decode(pdfUrl, "UTF-8");
        log.info("ready to download pdf: {}", pdfUrl);
        log.info("target file: {}", fileName);
        CloseableHttpClient httpClient = createSSLClientDefault();
        HttpGet get = new HttpGet(pdfUrl);
        addRequestHeader(get);

        while (true) {
            try {
                CloseableHttpResponse response = httpClient.execute(get);
                HttpEntity entity = response.getEntity();
                InputStream inputStream = entity.getContent();

                PDDocument document = PDDocument.load(inputStream);
                document.save(fileName);
                document.close();
                inputStream.close();
                response.close();
                break;
            } catch (Exception e) {
                log.error(e.getMessage());
            }
//            try (CloseableHttpResponse response = httpClient.execute(get)) {
//                HttpEntity entity = response.getEntity();
//                InputStream inputStream = entity.getContent();
//
//                PDDocument document = PDDocument.load(new BufferedInputStream(inputStream));
//                document.save(fileName);
//                document.close();

//                BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
//                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(fileName));
//                byte[] bs = new byte[1024];
//                int count = inputStream.read(bs);
//                while (count > 0) {
//                    bufferedOutputStream.write(bs, 0, count);
//                    count = inputStream.read(bs);
//                }
//                bufferedOutputStream.flush();
//                bufferedOutputStream.close();
//            }
        }
    }

    private String getPageContent(String url) throws Exception {
        log.info("ready to get page content: {}", url);
        CloseableHttpClient httpClient = createSSLClientDefault();
        HttpGet get = new HttpGet(url);
        addRequestHeader(get);
        try (CloseableHttpResponse response = httpClient.execute(get)) {
            HttpEntity entity = response.getEntity();
            String respBody = EntityUtils.toString(entity);
//            log.info("response body: {}", respBody);
            return respBody;
        }
    }

    private static CloseableHttpClient httpClient = null;

    private static CloseableHttpClient createSSLClientDefault() {
        if (httpClient != null) {
            return httpClient;
        }
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                    return true;
                }
            }).build();
            HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);
            httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
            return httpClient;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }

    private static void addRequestHeader(HttpRequest request) {
        request.addHeader("Accept", "application/json, text/plain, */*");
        request.addHeader("Accept-Language", "zh-CN,zh;q=0.9");
        request.addHeader("Connection", "keep-alive");
        request.addHeader("Content-Type", "application/json");
        request.addHeader("Sec-Fetch-Dest", "empty");
        request.addHeader("Sec-Fetch-Mode", "cors");
        request.addHeader("Sec-Fetch-Site", "same-origin");
        request.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36");
        request.addHeader("sec-ch-ua", "\"Google Chrome\";v=\"117\", \"Not;A=Brand\";v=\"8\", \"Chromium\";v=\"117\"");
        request.addHeader("sec-ch-ua-mobile", "?0");
        request.addHeader("sec-ch-ua-platform", "\"Windows\"");
    }
}
